/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.functors;

import org.jetbrains.annotations.NotNull;

public abstract class SestaryFunctor<A, B, C, D, E, F>
{
	public abstract void closure(@NotNull final A a, final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f);

	@NotNull
	public final SestaryFunctor<A, B, C, D, E, F> curry()
	{
		return this;
	}

	@NotNull
	public final QuinaryFunctor<A, B, C, D, E> curry(final @NotNull F f)
	{
		return new QuinaryFunctor<A, B, C, D, E>()
		{
			public void closure(@NotNull final A a, final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public final QuaternaryFunctor<A, B, C, D> curry(final @NotNull E e, final @NotNull F f)
	{
		return new QuaternaryFunctor<A, B, C, D>()
		{
			public void closure(@NotNull final A a, final @NotNull B b, final @NotNull C c, final @NotNull D d)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public final TernaryFunctor<A, B, C> curry(final @NotNull D d, final @NotNull E e, final @NotNull F f)
	{
		return new TernaryFunctor<A, B, C>()
		{
			public void closure(@NotNull final A a, final @NotNull B b, final @NotNull C c)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public final BinaryFunctor<A, B> curry(final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f)
	{
		return new BinaryFunctor<A, B>()
		{
			public void closure(@NotNull final A a, final @NotNull B b)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public final UnaryFunctor<A> curry(final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f)
	{
		return new UnaryFunctor<A>()
		{
			public void closure(@NotNull final A a)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public final NullaryFunctor curry(final @NotNull A a, final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f)
	{
		return new NullaryFunctor()
		{
			public void closure()
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
			}
		};
	}

	@NotNull
	public SestaryReturningFunctor<A, B, C, D, E, F, Nothing> toReturningFunctor()
	{
		return new SestaryReturningFunctor<A, B, C, D, E, F, Nothing>()
		{
			@NotNull
			public Nothing closure(final @NotNull A a, final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f)
			{
				SestaryFunctor.this.closure(a, b, c, d, e, f);
				return Nothing.Nothing;
			}
		};
	}

	@NotNull
	public static <A, B, C, D, E, F> SestaryFunctor<A, B, C, D, E, F> identitySestaryFunctor()
	{
		return new SestaryFunctor<A, B, C, D, E, F>()
		{
			public void closure(final @NotNull A a, final @NotNull B b, final @NotNull C c, final @NotNull D d, final @NotNull E e, final @NotNull F f)
			{
			}
		};
	}
}